package cn.android666.mediacodecsynchronous.permission

import android.content.pm.PackageManager
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentActivity
import cn.android666.mediacodecsynchronous.App
import timber.log.Timber

/**
 * 普通权限的申请工具，比如摄像头权限、定位权限等（区别于流量统计权限、Android11文件管理权限等的一些特殊权限）。
 * 使用步骤为：1、调用setRequestPermissions()来设置需要的权限。2、调用registerForActivityResult()注册结果监听器。3、调用requestPermissions()请求权限并接收结果
 */
object NormalPermissionUtil {

    /** 正常权限结果的启动器（比如写SD卡权限、读取电话状态权限等） */
    private lateinit var launcher: ActivityResultLauncher<Array<String>>
    private lateinit var resultCallback: () -> Unit

    // 声明需要申请的权限和对应的权限名称
    private lateinit var requestPermissions: Map<String, String>

    /**
     * 设置需要请求的权限，并且要求给每个权限起一个中文名字，以方便进行提示，示例如下：
     * mapOf(Manifest.permission.CAMERA to "摄像头", Manifest.permission.ACCESS_FINE_LOCATION to "定位")
     */
    fun setRequestPermissions(requestPermissions: Map<String, String>) {
        this.requestPermissions = requestPermissions
    }

    /**
     * 动态申请应用中需要的权限，权限在requestPermissions变量中进行声明。当获得所有权限时回调给hasAllPermission函数。
     * 注：在onCreate函数中调用
     * 需求：
     * androidx.activity，1.2.0 或更高版本。
     * androidx.fragment，1.3.0 或更高版本。
     * 示例如下：
     * implementation "androidx.activity:activity-ktx:1.3.0"
     * implementation "androidx.fragment:fragment-ktx:1.3.6"
     */
    fun registerForActivityResult(activity: FragmentActivity) {
        launcher = activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: Map<String, Boolean> ->
            Timber.i("普通权限申请结果：$result")
            val deniedPermissions = mutableListOf<String>()     // 被拒绝的权限
            val neverTipPermissions = mutableListOf<String>()   // 被设置不再提示的权限
            for ((permission, granted) in result) {
                if (!granted) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
                        // 权限被拒绝
                        deniedPermissions.add(permission)
                    } else {
                        // 权限被设置为不再提示
                        neverTipPermissions.add(permission)
                    }
                }
            }

            if (deniedPermissions.isEmpty() && neverTipPermissions.isEmpty()) {
                Timber.i("所有普通权限都允许了，恭喜！")
                resultCallback()
            } else {
                showTipDialog(activity, deniedPermissions, neverTipPermissions)
            }
        }
    }


    /** 请求普通权限  */
    fun requestPermissions(hasAllPermission: () -> Unit) {
        this.resultCallback = hasAllPermission
        val permissions = requestPermissions.keys.toTypedArray()
        val noGrantedPermission = mutableListOf<String>()
        for (permission in permissions) {
            if (ActivityCompat.checkSelfPermission(App.app, permission) != PackageManager.PERMISSION_GRANTED) {
                noGrantedPermission.add(permission)
            }
        }
        if (noGrantedPermission.isEmpty()) {
            hasAllPermission()
        } else {
            launcher.launch(noGrantedPermission.toTypedArray())
        }
    }

    private fun showTipDialog(activity: FragmentActivity, deniedPermissions: MutableList<String>, neverTipPermissions: MutableList<String>) {
        val desc: String
        val permissions: MutableList<String>

        if (deniedPermissions.isNotEmpty()) {
            // 权限被拒绝
            permissions = deniedPermissions
            desc = "本App需要使用%s权限，请允许此权限，否则无法使用本app"
        } else {
            // 权限被设置为不再提示
            permissions = neverTipPermissions
            desc = "本App需要使用%s权限，您需要到设置中打开此权限，否则无法使用本app"
        }

        val allPermissionDesc = StringBuilder()
        permissions.forEachIndexed { index, permission ->
            if (index > 0) allPermissionDesc.append("、")
            allPermissionDesc.append(requestPermissions[permission])
        }

        val message = String.format(desc, allPermissionDesc)
        Timber.w(message)

        UiUtil.showOneButtonDialog(activity, message) {
            requestPermissions(resultCallback)
        }
    }

}